package com.thunder.reader.transaction;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import com.thunder.reader.FeedSettings;
import com.thunder.reader.ReaderBaseException;
import com.thunder.reader.data.FoxReader;
import com.thunder.reader.data.Rss;
import com.thunder.reader.provider.Feed;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

public class RestoreAgent {
    private static final String TAG = "RestoreAgent";
    private ContentResolver mContentResolver;
    private InputStream mInputStream;
    private boolean mInterruptParsing;
    
    public RestoreAgent(ContentResolver cr, InputStream is) {
        mContentResolver = cr;
        mInputStream = is;
        mInterruptParsing = false;
    }
    
    public void restore() throws IOException, XmlPullParserException, ReaderBaseException {
        if (mInputStream == null) {
            throw new IOException("null input stream. did you initialize the class correctly?");
        }
        final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        factory.setNamespaceAware(true);
        final XmlPullParser parser = factory.newPullParser();
        
        parser.setInput(mInputStream, null);
        int eventType = parser.getEventType();
        if (eventType != XmlPullParser.START_DOCUMENT) {
            throw new ReaderBaseException("Not starting with 'start_document'");
        }
        eventType = restoreFoxReader(parser);
        if (!mInterruptParsing && eventType != XmlPullParser.END_DOCUMENT) {
            throw new ReaderBaseException("not ending with 'end_document', do you finish parsing?");
        }
        if (mInputStream != null) {
            mInputStream.close();
        } else {
            Log.e(TAG, "inputstream is null, XmlPullParser closed it??");
        }
    }
    
    private int restoreFoxReader(XmlPullParser parser) throws XmlPullParserException, IOException, ReaderBaseException {
        int eventType = parser.getEventType();
        if (eventType != XmlPullParser.START_DOCUMENT) {
            throw new ReaderBaseException("not starting with 'start_document', is this a new document?");
        }
        eventType = parser.next();
        while (!mInterruptParsing && eventType != XmlPullParser.END_DOCUMENT) {
            switch (eventType) {
            case XmlPullParser.START_TAG: {
                Log.e(TAG, "start tag: '" + parser.getName() + "'");
                final String tagName = parser.getName();
                if (tagName.equals(FoxReader.TAG_FOX_READER)) {
                    Log.e(TAG, "starting fox reader");
                } else if (tagName.equals(FoxReader.TAG_GROUP)) {
                    restoreGroup(parser);
                } 
                break;
            }
            case XmlPullParser.END_TAG: {
                Log.e(TAG, "end tag: '" + parser.getName() + "'");
                final String tagName = parser.getName();
                if (tagName.equals(FoxReader.TAG_FOX_READER)) {
                    Log.e(TAG, ">> edning an fox reader");
                }
                break;
            }
            default:
                break;
            }
            eventType = parser.next();
        }
        return parser.getEventType();
    }
    
    private int restoreGroup(XmlPullParser parser) throws IOException, XmlPullParserException, ReaderBaseException {
        int eventType = parser.getEventType();
        String tag = parser.getName();
        if (eventType != XmlPullParser.START_TAG || !tag.equals(FoxReader.TAG_GROUP)) {
            throw new ReaderBaseException("invalid start of group");
        }
        final ContentValues cv = new ContentValues();
        String title = parser.getAttributeValue(null, Rss.TAG_TITLE);
        title = URLDecoder.decode(title, FeedSettings.getDefaultEncoding());
        cv.put(Feed.Group.TITLE, title);
        String description = parser.getAttributeValue(null, Rss.TAG_DESCRIPTION);
        description = URLDecoder.decode(description, FeedSettings.getDefaultEncoding());
        cv.put(Feed.Group.DESCRIPTION, description);
        final Uri uri = mContentResolver.insert(Feed.Group.CONTENT_URI, cv);
        eventType = parser.nextTag();
        tag = parser.getName();
        while (!mInterruptParsing && eventType == XmlPullParser.START_TAG && tag.equals(FoxReader.TAG_SOURCE)) {
            eventType = restoreFeed(parser, uri);
            if (eventType != XmlPullParser.END_TAG) {
                throw new ReaderBaseException("invalid end of source, did you finish parsing");
            }
            eventType = parser.nextTag();
        }
        return eventType;
    }
    
    private int restoreFeed(XmlPullParser parser, Uri groupUri) throws XmlPullParserException, ReaderBaseException, IOException {
        int eventType = parser.getEventType();
        String tag = parser.getName();
        if (eventType != XmlPullParser.START_TAG || !tag.equals(FoxReader.TAG_SOURCE)) {
            throw new ReaderBaseException("invalid start of source");
        }
        final ContentValues cv = new ContentValues();
        String title = parser.getAttributeValue(null, Rss.TAG_TITLE);
        title = URLDecoder.decode(title, FeedSettings.getDefaultEncoding());
        cv.put(Feed.Source.TITLE, title);
        String description = parser.getAttributeValue(null, Rss.TAG_DESCRIPTION);
        description = URLDecoder.decode(description, FeedSettings.getDefaultEncoding());
        cv.put(Feed.Source.DESCRIPTION, description);
        final String xmlUrl = parser.getAttributeValue(null, FoxReader.TAG_XML_URL);
        if (!TextUtils.isEmpty(xmlUrl)) {
            cv.put(Feed.Source.FEED_URL, xmlUrl);
        }
        final String htmlUrl = parser.getAttributeValue(null, FoxReader.TAG_HTML_URL);
        if (!TextUtils.isEmpty(htmlUrl)) {
            cv.put(Feed.Source.URL, htmlUrl);
        }
        final String imageUrl = parser.getAttributeValue(null, FoxReader.TAG_IMAGE_URL);
        if (!TextUtils.isEmpty(imageUrl)) {
            cv.put(Feed.Source.IMAGE_URL, imageUrl);
        }
        cv.put(Feed.Source.GROUP_ID, groupUri.getPathSegments().get(1));
        final Uri sourceUri = mContentResolver.insert(Feed.Source.CONTENT_URI, cv);
        eventType = parser.nextTag();
        tag = parser.getName();
        while (!mInterruptParsing && eventType == XmlPullParser.START_TAG && tag.equals(FoxReader.TAG_ARTICLE)) {
            eventType = restoreArticles(parser, groupUri, sourceUri);
            if (eventType != XmlPullParser.END_TAG) {
                throw new ReaderBaseException("invalid end of article, did you finish parsing");
            }
            eventType = parser.nextTag();
        }
        return eventType;
    }
    
    private int restoreArticles(XmlPullParser parser, Uri groupUri, Uri sourceUri) throws XmlPullParserException, ReaderBaseException, IOException {
        int eventType = parser.getEventType();
        String tag = parser.getName();
        if (eventType != XmlPullParser.START_TAG || !tag.equals(FoxReader.TAG_ARTICLE)) {
            throw new ReaderBaseException("invalid start of source");
        }
        final ContentValues cv = new ContentValues();
        String title = parser.getAttributeValue(null, Rss.TAG_TITLE);
        title = URLDecoder.decode(title, FeedSettings.getDefaultEncoding());
        cv.put(Feed.Article.TITLE, title);
        String description = parser.getAttributeValue(null, Rss.TAG_DESCRIPTION);
        description = URLDecoder.decode(description, FeedSettings.getDefaultEncoding());
        cv.put(Feed.Article.DESCRIPTION, description);
        cv.put(Feed.Article.SOURCE_ID, sourceUri.getPathSegments().get(1));
        cv.put(Feed.Article.GROUP_ID, groupUri.getPathSegments().get(1));
        cv.put(Feed.Article.ARTICLE_URL, parser.getAttributeValue(null, FoxReader.TAG_ARTICLE_URL));
        cv.put(Feed.Article.IMAGE_URL, parser.getAttributeValue(null, FoxReader.TAG_IMAGE_URL));
        cv.put(Feed.Article.PUB_DATE, parser.getAttributeValue(null, Rss.TAG_PUBDATE));
        cv.put(Feed.Article.READ, parser.getAttributeValue(null, FoxReader.TAG_READ));
        return parser.nextTag();
    }
}